package com.gonsin.gview.logic.services.dynamicData;

import com.gonsin.base.exceptions.MyException;
import com.gonsin.gview.logic.GViewEnvironment;
import com.gonsin.gview.logic.db.SqlExecutor;
import com.gonsin.gview.logic.enums.GViewResultCodes;
import com.gonsin.gview.logic.exceptions.BaseGViewException;
import com.gonsin.gview.logic.model.DataRequest;
import com.gonsin.gview.logic.utils.FreemarkerUtils;
import com.gonsin.gview.logic.utils.MustacheUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Component
public class DataUtils {

    @Autowired
    private SqlExecutor sqlExecutor;


    /**
     * 查询数据库
     * @param sql 设置的sql
     * @param single
     * @param request
     * @param response
     * @return
     */
    public Object generalDataFromSql(String sql, boolean single, HttpServletRequest request, HttpServletResponse response, Map<String, Object> props) {

        long now = System.currentTimeMillis();

        List<String> sessionKeys = parseSessionKeys(sql);


        try {
            // 注入动态变量
            String temp = sql;
            Map<String, String> sessionMap = new HashMap<>();
            if(!CollectionUtils.isEmpty(sessionKeys)){
                HttpSession session = request.getSession();
                for(String key : sessionKeys){
                    Object sessionValue = session.getAttribute(key);
                    if(sessionValue == null){
                        log.error(String.format("执行sql语句“%s”的时候发生错误，找到session值【%s】为空", sql, key));
                        throw new MyException(GViewResultCodes.USER_TIMEOUT);
                    }
                    String value = Objects.toString(sessionValue);
                    sessionMap.put(key, value);
                }
            }
            if(props == null){
                props = new HashMap<>();
            }
            props.put("session", sessionMap);

            // 注入表单变量
            //        List<KeyValue> kvs = dataRequest.getProps();
            //        if(!CollectionUtils.isEmpty(kvs)){
            //            kvs.forEach(kv -> {
            //                data.put(kv.getKey(), kv.getValue());
            //            });
            //        }
            try {
                if(GViewEnvironment.LOG){
                    log.info("执行查询(转化前) " + sql);
                }
                temp = FreemarkerUtils.generalString(sql, props);
                temp = MustacheUtils.generalString(temp, props);
                if(GViewEnvironment.LOG){
                    log.info("执行查询(转化前) " + temp);
                    log.info("请查看SQL结果是否和预期相同：");
                }
            } catch (Exception ex) {
                throw new BaseGViewException("freeMarker转换出错，sql语句为" + sql + "，可能里面的变量不正确。");
//                log.error(ex.toString(), ex);

//                return null;
            }
            try {
                if(single){
                    return sqlExecutor.executeSingleQuery(temp);
                } else {
                    return sqlExecutor.executeQuery(temp);
                }
            } catch (SQLException ex) {
                log.warn("查询的sql文本" + temp);
                //            throwables.printStackTrace();
                log.error(ex.toString(), ex);
                throw new BaseGViewException(String.format("数据库查询失败，查询语句为%s", temp));
                //            throw new DataQueryException(temp);
            }
        } finally {
            long delay = System.currentTimeMillis() - now;
            if(GViewEnvironment.LOG){
                log.info("SQL 查询耗时: " + new SimpleDateFormat("ss.SSS").format(delay) + "秒");
            }
        }
    }

    private List<String> parseSessionKeys(String sql) {
        List<String> sessionKeys = new ArrayList();

        // 检测session的内容
        if(sql.contains("${session.")){
            String temp = sql;

            // 提取所有session的字段
            int readIndex = temp.indexOf("${session.") + 10;
            while(readIndex >= 10){
                temp = temp.substring(readIndex);
                int nameLength = temp.indexOf("}");
                String name = temp.substring(0, nameLength);
                sessionKeys.add(name);
                readIndex = temp.indexOf("${session.") + 10;
            }
        }

        if(sql.contains("{{session.")){


            String temp = sql;
            // 提取所有session的字段
            int readIndex = temp.indexOf("{{session.") + 10;
            while(readIndex >= 10){
                temp = temp.substring(readIndex);
                int nameLength = temp.indexOf("}}");
                String name = temp.substring(0, nameLength);
                sessionKeys.add(name);
                readIndex = temp.indexOf("{{session.") + 10;
            }
        }

        return sessionKeys;
    }

}
